#!/bin/bash -
#===============================================================================
#
#          File: git-vergen
#
#         Usage: ./git-vergen
#
#   Description: Generate version info base on the tag
#
#       Options: ---
#  Requirements: ---
#          Bugs: ---
#         Notes: ---
#        Author: ShadowStar, <orphen.leiliu@gmail.com>
#  Organization:Gmail
#       Created: 12/23/15 14:06:09
#   Last Change:  08/01/2018 22:00:52
#      Revision:  ---
#===============================================================================

set -o nounset                              # Treat unset variables as an error

export LC_ALL=POSIX
export LANG=POSIX

COMMIT=
FULL=
NOW=
HEAD=
DIR=$PWD
REL=
OUTPUT=

usage () {
	echo "Usage: $0 [-r|--release <addition tag>] [-c|--commit] [-f|--full[-n|--now]] [-d|--dir <git path>] [<commit id>]"
	echo "       -r|--release    -- addition release tag, like alpha, beta, etc..."
	echo "       -c|--commit     -- show commit id"
	echo "       -f|--full       -- display full message"
	echo "       -n|--now        -- use current user & time instead of commit info"
	echo "       -d|--dir <dir>  -- use <dir> as git work tree instead of \$(pwd)"
	echo "       <commit id>     -- use <commit id> instead of HEAD"
	exit -1
}

[ $# -le 7 ] || usage

until [ $# -eq 0 ]; do
	case "$1" in
		-r|--release)
			REL="$2";
			shift 2;;
		-c|--commit)
			COMMIT=1;
			shift ;;
		-f|--full)
			COMMIT=1;
			FULL=1;
			shift ;;
		-n|--now)
			NOW=1;
			shift ;;
		-d|--dir)
			if [ $# -eq 1 ]; then
				usage
			else
				DIR="$2"
				shift 2
			fi ;;
		-*)
			usage ;;
		*)
			HEAD="$1";
			shift ;;
	esac
done

git_dir=${DIR}

[ -e "${git_dir}/.git" ] && git_dir=${git_dir}/.git

export GIT_DIR=${git_dir}
export GIT_WORK_TREE=${git_dir%/.git}

check () {
	git rev-parse --short ${HEAD:-HEAD} 1>/dev/null 2>&1 || \
		(echo -n "[${DIR}] isn't a git work tree" &&
		if [ -n "$HEAD" -a "$HEAD" != "HEAD" ]; then
			echo " or commit id <${HEAD}> NOT found."
		else
			echo "."
		fi && return 255)
}

check || exit -1

desc_info () {
	local desc
	desc=$(git describe --tags --long --always ${HEAD} 2>/dev/null)
	$(echo ${desc} | grep -q '\-g[0-9a-fA-F]\+$') || \
		desc="0.0-$(git log --oneline | wc -l | tr -d '[[:space:]]')-g${desc}"
	echo "${desc}"
}

DESC=$(desc_info)

get_version() {
	local ver patch
	ver=$(echo ${DESC} | cut -d'-' -f 1 | sed -e 's|^[vV]||')
	patch=$(echo ${DESC} | cut -d'-' -f 2)
	echo ${ver}.${patch}
}

commit_info () {
	echo ${DESC} | cut -d'-' -f 3 | cut -c 2-
}

dirty_info () {
	dirty=$(git describe --always --dirty ${HEAD} 2>/dev/null | grep "\-dirty$")
	echo "${dirty:+x}"
}

branch_info () {
	git branch --contain ${HEAD} | grep "^\*" | cut -d' ' -f 2- 2>/dev/null
}

log_info () {
	git log --abbrev-commit --max-count=1 --date=iso ${HEAD} | head -n4
}

author_date_info () {
	if [ -n "$NOW" ]; then
		echo "$(whoami) @$(uname -n).$(uname -s) $(date '+%Y-%m-%d %T %z')"
	else
		echo $(log_info) | sed -e 's|.*Author: \(.*\) Date: \(.*\)|\1 \2|'
	fi
}

OUTPUT="$(get_version)${COMMIT:+-$(commit_info)}$(dirty_info)${REL}"
ADDITION="${FULL:+ ($(branch_info) $(author_date_info))}"

echo ${OUTPUT}${ADDITION}
